﻿Imports OMANE.Common.UI
Imports System.Collections.ObjectModel
Imports PTIC_GestionBDD
Imports Microsoft.Practices.Prism.Commands


Namespace ViewModels
    Public Class ViewModelSimulation
        Inherits ViewModelCommand
        Implements IViewModelTabSection

        Dim WithEvents _simulations As New ObservableCollection(Of ViewModelSimulationElement)
        Dim _owner As ICollection(Of IViewModelTabSection)

        Public Property Icone As String Implements Common.UI.IViewModelTabSection.Icone
        Public Property Title As String Implements Common.UI.IViewModelTabSection.Title
        Public Property IsClosable As Boolean Implements IViewModelTabSection.IsClosable

        Sub New()
            'AddHandler _simulations.CollectionChanged, AddressOf SimulationsChanged
            'Try
            '    For Each e In Locator.ModelStatic.Univers.listeTraitements.TraitMoteurMethode2.Simulations.Values
            '        _simulations.Add(New ViewModelSimulationElement(e))
            '    Next
            'Catch ex As Exception

            'End Try
        End Sub

        Public ReadOnly Property Simulations As ObservableCollection(Of ViewModelSimulationElement)
            Get
                Return _simulations
            End Get
        End Property

        Friend Sub SetOwner(ByVal owner As ICollection(Of IViewModelTabSection))
            _owner = owner
        End Sub

        Private emptyresult As New Dictionary(Of ViewModelSimulationElement, ViewModelSimulationResult)
        Private Sub _simulations_CollectionChanged(ByVal sender As Object, ByVal e As System.Collections.Specialized.NotifyCollectionChangedEventArgs) Handles _simulations.CollectionChanged
            Select Case e.Action
                Case Specialized.NotifyCollectionChangedAction.Add
                    '_owner.Add(New ViewModelSimulationResult())
                    Dim newsimulation As ViewModelSimulationElement = e.NewItems(0)
                    AddHandler newsimulation.ResultChange, AddressOf SimulationResultChange
                    AddHandler newsimulation.NameChange, AddressOf SimulationNameChange
                    'emptyresult.Add(newsimulation, _owner.Last())
                Case Specialized.NotifyCollectionChangedAction.Remove
                    Dim newsimulation As ViewModelSimulationElement = e.OldItems(0)
                    RemoveHandler newsimulation.ResultChange, AddressOf SimulationResultChange
                    RemoveHandler newsimulation.NameChange, AddressOf SimulationNameChange

                    If newsimulation.Result IsNot Nothing Then
                        If _owner.Contains(newsimulation.Result) Then
                            _owner.Remove(newsimulation.Result)
                        End If
                    End If
                    'Dim brother = emptyresult(e.OldItems(0))
                    'emptyresult.Remove(e.OldItems(0))
                    '_owner.Remove(brother)
            End Select
        End Sub
        Private Sub SimulationResultChange(ByVal sender As Object, ByVal e As EventArgs)
            Dim simulation As ViewModelSimulationElement = sender

            If simulation.Result IsNot Nothing Then
                If Not _owner.Contains(simulation.Result) Then
                    Dim d = Windows.Application.Current.Dispatcher
                    d.Invoke(Sub() _owner.Add(simulation.Result))
                End If
            End If
            'If emptyresult.ContainsKey(simulation) Then
            '    If simulation.Result IsNot Nothing Then
            '        _owner.Remove(emptyresult(simulation))
            '        emptyresult(simulation) = simulation.Result
            '        _owner.Add(simulation.Result)
            '    End If
            'End If
        End Sub
        Private Sub SimulationNameChange(ByVal sender As Object, ByVal e As EventArgs)
            Dim simulation As ViewModelSimulationElement = sender
            If simulation.Result IsNot Nothing Then
                simulation.Result.Title = simulation.Name.ToUpper()
            End If
        End Sub

    End Class

    Public Class ViewModelSimulationElement
        Inherits ViewModelBase

        Private simulation As moteurTauxGaranti2.SimulIndMoteur2

        Sub New()
            simulation = New moteurTauxGaranti2.SimulIndMoteur2( _
                Locator.ModelStatic.ListeTraitements.TraitMoteurMethode2)
        End Sub

        Sub New(ByVal simulation As moteurTauxGaranti2.SimulIndMoteur2)
            Me.simulation = simulation
        End Sub

        Private _Name As String
        Private WithEvents _parameters As New ObservableCollection(Of ViewModelSimulationElementParameter)

        Public Property Name As String
            Get
                Return simulation.Description
            End Get
            Set(ByVal value As String)
                OnPropertyChanging("Name")
                simulation.Description = value
                RaiseEvent NameChange(Me, EventArgs.Empty)
                OnPropertyChanged("Name")
            End Set
        End Property
        Public Event NameChange As EventHandler

        Public Property Time As TimeSpan
            Get
                Return simulation.TempsCalcul
            End Get
            Set(ByVal value As TimeSpan)
                OnPropertyChanging("Time")
                'simulation.TempsCalcul = value
                OnPropertyChanged("Time")
            End Set
        End Property


        Private _ComputationState As Object
        Public Property ComputationState As Object
            Get
                Return simulation.EtatCalcul.ToString()
            End Get
            Set(ByVal value As Object)
                OnPropertyChanging("ComputationState")
                OnPropertyChanged("ComputationState")
            End Set
        End Property


        Private _ComputationProgress As Double
        Public Property ComputationProgress As Double
            Get
                Return _ComputationProgress
            End Get
            Set(ByVal value As Double)
                OnPropertyChanging("ComputationProgress")
                _ComputationProgress = value
                OnPropertyChanged("ComputationProgress")
            End Set
        End Property



        Private _ShowBt As Boolean = True
        Public Property ShowBt As Boolean
            Get
                Return _ShowBt
            End Get
            Set(ByVal value As Boolean)
                _ShowBt = value
                OnPropertyChanged("ShowBt")
                OnPropertyChanged("ShowPb")
            End Set
        End Property
        Public Property ShowPb As Boolean
            Get
                Return Not ShowBt
            End Get
            Set(ByVal value As Boolean)
                ShowBt = Not value
            End Set
        End Property



        Public ReadOnly Property Parameters As ObservableCollection(Of ViewModelSimulationElementParameter)
            Get
                Return _parameters
            End Get
        End Property


        Private _Result As ViewModelSimulationResult
        Public Property Result As ViewModelSimulationResult
            Get
                Return _Result
            End Get
            Set(ByVal value As ViewModelSimulationResult)
                OnPropertyChanging("Result")
                _Result = value
                RaiseEvent ResultChange(Me, EventArgs.Empty)
                OnPropertyChanged("Result")
            End Set
        End Property
        Public Event ResultChange As EventHandler


        Private _LaunchCommand As New DelegateCommand(Of Object)(AddressOf LaunchExecute, AddressOf LaunchCanExecute)
        Public ReadOnly Property LaunchCommand As DelegateCommand(Of Object)
            Get
                Return _LaunchCommand
            End Get
        End Property
        Private Sub LaunchExecute(ByVal parameter As Object)
            ShowPb = True
            Dim simmethod = Sub() simulation.Calculer()
            Dim simcallback = Sub(sender As Object, e As System.EventArgs)
                                  Dim r = New ViewModelSimulationResult( _
                                                    simulation.Resultats, _
                                                     Parameters.Count > 1, _
                                                     Name.ToUpper())
                                  Result = r
                                  ShowPb = False
                              End Sub

            'Dim op = Windows.Threading.Dispatcher.CurrentDispatcher.BeginInvoke(simmethod, _
            '         Windows.Threading.DispatcherPriority.SystemIdle)
            'AddHandler op.Completed, simcallback

            Dim cb = Sub(c As IAsyncResult)
                         simcallback(Nothing, Nothing)
                     End Sub
            simmethod.BeginInvoke(cb, Nothing)
        End Sub
        Private Function LaunchCanExecute(ByVal parameter As Object) As Boolean
            Return True
        End Function

        Private Sub _parameters_CollectionChanged(ByVal sender As Object, ByVal e As System.Collections.Specialized.NotifyCollectionChangedEventArgs) Handles _parameters.CollectionChanged
            Select Case e.Action
                Case Specialized.NotifyCollectionChangedAction.Add
                    simulation.listeParametres.Add(e.NewItems(0).Parametre)
                Case Specialized.NotifyCollectionChangedAction.Remove
                    simulation.listeParametres.Remove(e.OldItems(0).Parametre)
            End Select
        End Sub
    End Class

    Public Class ViewModelSimulationElementParameter
        Inherits ViewModelBase

        Private _parametre As moteurTauxGaranti2.ParamSimulInd


        Public ReadOnly Property Parametre As moteurTauxGaranti2.ParamSimulInd
            Get
                Return _parametre
            End Get
        End Property

        Sub New()
            _parametre = New moteurTauxGaranti2.ParamSimulInd()
        End Sub


        Sub New(ByVal parametre As moteurTauxGaranti2.ParamSimulInd)
            Me._parametre = parametre
        End Sub


        Public Property VariationStep As Double
            Get
                Return Parametre.Pas
            End Get
            Set(ByVal value As Double)
                OnPropertyChanging("VariationStep")
                Parametre.Pas = value
                OnPropertyChanged("VariationStep")
            End Set
        End Property


        Public Property Min As Double
            Get
                Return Parametre.chocMin
            End Get
            Set(ByVal value As Double)
                OnPropertyChanging("Min")
                Parametre.chocMin = value
                OnPropertyChanged("Min")
            End Set
        End Property


        Public Property Max As Double
            Get
                Return Parametre.chocMax
            End Get
            Set(ByVal value As Double)
                OnPropertyChanging("Max")
                Parametre.chocMax = value
                OnPropertyChanged("Max")
            End Set
        End Property

        Public ReadOnly Property Variables As IEnumerable
            Get
                Return From e In Locator.ModelStatic.ListeParametres
                       Where e.Value.Type Is GetType(Double)
                       Select e.Key
            End Get
        End Property


        Public Property SelectedVariable As Object
            Get
                Return Parametre.Nom
            End Get
            Set(ByVal value As Object)
                OnPropertyChanging("SelectedVariable")
                Parametre.Nom = value
                OnPropertyChanged("SelectedVariable")
            End Set
        End Property


    End Class


    Public Class ViewModelSimulationResult
        Inherits ViewModelCommand
        Implements IViewModelTabSection

        Dim _SimulationData As DataTable
        Dim _GraphData As DataView
        Dim _TriData As Collections.IEnumerable
        Dim _VanData As Collections.IEnumerable
        Dim _FilteringData As DataView

        Public Function Clone() As ViewModelSimulationResult
            Dim r As New ViewModelSimulationResult
            Icone = OMANE.Common.UI.Theme.StandardIcons.COMPASS
            r.Title = Me.Title
            r._SimulationUseMultipleVariable = Me._SimulationUseMultipleVariable
            r._SimulationData = Me._SimulationData
            r.SimulationUseOneVariable = Me.SimulationUseOneVariable
            r._GraphData = Me._GraphData
            r._TriData = Me._TriData
            r._VanData = Me._VanData
            r._CurrentVariable = Me._CurrentVariable
            Return r
        End Function

        Sub New()
            Icone = OMANE.Common.UI.Theme.StandardIcons.COMPASS
        End Sub
        Sub New(ByVal data As DataTable, ByVal usemultiplevariable As Boolean, ByVal title As String)
            Icone = OMANE.Common.UI.Theme.StandardIcons.COMPASS
            Me.Title = title
            Me._SimulationUseMultipleVariable = usemultiplevariable
            Me._SimulationData = data
            If SimulationUseOneVariable Then
                _GraphData = _SimulationData.DefaultView
                _TriData = (From e As DataRowView In _GraphData Select X = e(0), Y = e("TRI")).AsEnumerable()
                _VanData = (From e As DataRowView In _GraphData Select X = e(0), Y = e("VAN")).AsEnumerable()
                _CurrentVariable = _SimulationData.Columns(0)
            End If
            If SimulationUseMultipleVariable Then
                _GraphData = _SimulationData.DefaultView
                CreateDataSet(data)
            End If
        End Sub

        Public Property IsClosable As Boolean Implements IViewModelTabSection.IsClosable

        Public Property Icone As String Implements Common.UI.IViewModelTabSection.Icone
        Private _Title As String
        Public Property Title As String Implements Common.UI.IViewModelTabSection.Title
            Get
                Return _Title
            End Get
            Set(ByVal value As String)
                OnPropertyChanging("Title")
                _Title = value
                OnPropertyChanged("Title")
            End Set
        End Property

        Public ReadOnly Property TriData As IEnumerable
            Get
                If _TriData Is Nothing Or _CurrentVariable Is Nothing Then Return From e In Enumerable.Range(1, 10) Select X = e, Y = (e - 5) * (e - 5)
                Return _TriData
            End Get
        End Property
        Public ReadOnly Property VanData As IEnumerable
            Get
                If _VanData Is Nothing Or _CurrentVariable Is Nothing Then Return From e In Enumerable.Range(1, 10) Select X = e, Y = (e - 4) * (e - 7)
                Return _VanData
            End Get
        End Property
        Public ReadOnly Property GraphData As DataView
            Get
                Return _GraphData
            End Get
        End Property

        Public ReadOnly Property FilteringData As DataView
            Get
                Return _FilteringData
            End Get
        End Property
        Public Property CurrentFilterOld As Object
            Get
                Return _CurrentFilter
            End Get
            Set(ByVal value As Object)
                OnPropertyChanging("CurrentFilter")
                _CurrentFilter = value



                If _CurrentFilter IsNot Nothing Then
                    If _CurrentVariable IsNot Nothing Then
                        Dim rv As DataRowView = _CurrentFilter
                        Dim filteringstring As String = ""

                        For i As Integer = 0 To _FilteringData.Table.Columns.Count - 1

                            If i > 0 Then
                                If (_FilteringData.Table.Columns.Count = 2) _
                                    Or (i < _FilteringData.Table.Columns.Count - 1) Then

                                    filteringstring = filteringstring & " And "
                                End If
                            End If

                            filteringstring = filteringstring & _
                                _FilteringData.Table.Columns(i).ColumnName & _
                                " = " & _
                                CDbl(rv(_FilteringData.Table.Columns(i).ColumnName)).ToString( _
                                    System.Globalization.CultureInfo.InvariantCulture)


                        Next

                        Dim temp As DataView = New DataView(_SimulationData)
                        temp.RowFilter = filteringstring
                        temp.Sort = _CurrentVariable.ColumnName

                        _GraphData = temp.ToTable(False, _
                              _CurrentVariable.ColumnName, _
                              "TRI", _
                              "VAN").DefaultView

                        UpdateGraphs()
                    End If
                End If

                OnPropertyChanged("CurrentFilter")
            End Set
        End Property



        Public ReadOnly Property SimulationData As DataTable
            Get
                Return _SimulationData
            End Get
        End Property




        Public Property CurrentVariableOld As DataColumn
            Get
                Return _CurrentVariable
            End Get
            Set(ByVal value As DataColumn)
                OnPropertyChanging("CurrentVariable")
                If value IsNot Nothing Then
                    If value IsNot _CurrentVariable Then
                        Dim cols = From c As DataColumn In _SimulationData.Columns Select c.ColumnName
                        Dim filtercols = cols.Except({"TRI", "VAN", value.ColumnName}).ToArray()
                        _FilteringData = _SimulationData.DefaultView.ToTable(True, filtercols).DefaultView
                        OnPropertyChanged("FilteringData")
                    End If
                Else
                    _TriData = Nothing
                    _VanData = Nothing
                    _CurrentFilter = Nothing
                    _FilteringData = Nothing
                    OnPropertyChanged("TriData")
                    OnPropertyChanged("VanData")
                    OnPropertyChanged("CurrentFilter")
                    OnPropertyChanged("FilteringData")
                End If
                _CurrentVariable = value
                OnPropertyChanged("CurrentVariable")
            End Set
        End Property

        Private Sub UpdateGraphs()
            _TriData = (From e As DataRowView In _GraphData Select X = e(_CurrentVariable.ColumnName), Y = e("TRI")).AsEnumerable()
            _VanData = (From e As DataRowView In _GraphData Select X = e(_CurrentVariable.ColumnName), Y = e("VAN")).AsEnumerable()


            OnPropertyChanged("TriData")
            OnPropertyChanged("VanData")
        End Sub




        Private _SimulationUseMultipleVariable As Boolean
        Public Property SimulationUseMultipleVariable As Boolean
            Get
                Return _SimulationUseMultipleVariable
            End Get
            Set(ByVal value As Boolean)
                OnPropertyChanging("SimulationUseOneVariable")
                OnPropertyChanging("SimulationUseMultipleVariable")
                _SimulationUseMultipleVariable = value
                OnPropertyChanged("SimulationUseOneVariable")
                OnPropertyChanged("SimulationUseMultipleVariable")
            End Set
        End Property
        Public Property SimulationUseOneVariable As Boolean
            Get
                Return Not SimulationUseMultipleVariable
            End Get
            Set(ByVal value As Boolean)
                SimulationUseMultipleVariable = Not value
            End Set
        End Property

        Private _dataset As DataSet = Nothing
        Private Sub CreateDataSet(ByVal source As DataTable)
            Try
                _dataset = New DataSet()
                Dim srcTable = source.Copy()
                srcTable.TableName = "tbl_source"
                _dataset.Tables.Add(srcTable)

                Dim trivancols = New DataColumn() { _
                    srcTable.Columns("TRI"), _
                    srcTable.Columns("VAN")}

                Dim varcols = Enumerable.Except( _
                    srcTable.Columns.Cast(Of DataColumn), _
                    trivancols).ToArray()

                Dim filtercols = _
                    Function(c As DataColumn)
                        Return (From elt In varcols
                               Where elt IsNot c
                               Select elt.ColumnName).ToArray()
                    End Function

                Dim vartables = (From c In varcols
                  Select srcTable.DefaultView.ToTable( _
                      "tbl_" & c.ColumnName, _
                      True, _
                      filtercols(c))).ToArray()

                Dim o = filtercols(varcols(0))
                Dim o2 = filtercols(varcols(1))
                _dataset.Tables.AddRange(vartables)

                Dim cols = _
                    Function(brother As DataTable, table As DataTable)
                        Return (From c As DataColumn In brother.Columns Select table.Columns(c.ColumnName)).ToArray()
                    End Function

                Dim varrelations = (From t In vartables
                   Select New DataRelation( _
                       "rel_" & t.TableName.Replace("tbl_", ""), _
                       t.Columns.Cast(Of DataColumn).ToArray(), _
                       cols(t, srcTable), True)).ToArray()


                _dataset.Relations.AddRange(varrelations)
            Catch ex As Exception
                _dataset = Nothing
            End Try
        End Sub
        Public ReadOnly Property Variables As IEnumerable(Of DataColumn)
            Get
                If _dataset Is Nothing Then Return Nothing
                If SimulationUseOneVariable Then Return Nothing
                Return _dataset.Tables("tbl_source").Columns.Cast(Of DataColumn).Take(_SimulationData.Columns.Count - 2)
            End Get
        End Property

        Private _CurrentVariable As DataColumn
        Public Property CurrentVariable As DataColumn
            Get
                Return _CurrentVariable
            End Get
            Set(ByVal value As DataColumn)
                OnPropertyChanging("CurrentVariable")
                If value IsNot Nothing Then
                    If value IsNot _CurrentVariable Then
                        _FilteringData = _dataset.Tables("tbl_" & value.ColumnName).DefaultView
                        OnPropertyChanged("FilteringData")
                    End If
                Else
                    _TriData = Nothing
                    _VanData = Nothing
                    _CurrentFilter = Nothing
                    _FilteringData = Nothing
                    OnPropertyChanged("TriData")
                    OnPropertyChanged("VanData")
                    OnPropertyChanged("CurrentFilter")
                    OnPropertyChanged("FilteringData")
                End If
                _CurrentVariable = value
                OnPropertyChanged("CurrentVariable")
            End Set
        End Property

        Private _CurrentFilter As Object
        Public Property CurrentFilter As Object
            Get
                Return _CurrentFilter
            End Get
            Set(ByVal value As Object)
                OnPropertyChanging("CurrentFilter")
                Dim rv As DataRowView = value
                If value IsNot Nothing Then
                    _GraphData = rv.CreateChildView("rel_" & CurrentVariable.ColumnName)
                    _CurrentFilter = value
                    UpdateGraphs()
                    OnPropertyChanged("CurrentFilter")
                End If
            End Set
        End Property
    End Class
End Namespace